package sms.annotation;

import sms.Student;

import java.lang.reflect.Field;

/**
 * Class类中的方法:
 *   public Field[] getDeclaredFields() throws SecurityException
 *     返回该类中所有的已声明的字段包括私有字段
 */
public class ValidationProcessor {
    /**
     *  验证给定的对象中的所有加了注解的字段,检验是否符合给定的规则
     * @param student
     * @return
     * @throws Exception
     */
    public static boolean validate(Student student)throws Exception {
        //1.设定一个变量isValid,如果有某个字段检验失败,就代表该对象不合法
        //isValid就会被设置为false
        boolean isValid = true;

        //2.获取字节码对象
        Class<? extends Student> stuClass = student.getClass();

        //3.获取指定的字节码中的所有字段(外层循环相当于沿着继承体系,从最底层子类一直校验顶级父类(仅次于Object类)为止)
        //for(int i=0;i<3;i++)
        for (Class<?> cls = student.getClass(); cls != Object.class; cls = cls.getSuperclass())
            for (Field field : cls.getDeclaredFields()) {
                //4.跳过Java的权限访问检查,能够用来设置和获取私有字段的值
                //暴力反射
                field.setAccessible(true);

                //5.判断字段上是否有@Validate注解,如果有在进行校验逻辑
                if (field.isAnnotationPresent(Validate.class)) {
                    //6.获取对象中指定字段的值
                    Object value = field.get(student);
                    //7.获取@Validate注解
                    Validate validation = field.getAnnotation(Validate.class);

                    //8.处理正则表达式校验
                    if (!validation.regex().isEmpty() && field.getType().equals(String.class)) {
                        //如果正则表达式不为空串并且字段属性类型为String类型
                        String strVal = (String) value;
                        if (!strVal.matches(validation.regex())) {
                            System.out.println("字段 "+field.getName()+" 的格式校验失败");
                            isValid = false;
                        }
                    }

                    //9.处理分数值校验
                    if (field.getType().equals(Integer.class)) {
                        if (value != null) {
                            Integer integerVal = (Integer) value;
                            if (integerVal < validation.min() || integerVal > validation.max()) {
                                //判断integerVal超出了[min,max]范围
                                System.out.println("字段 "+field.getName()+" 的校验数值范围失败");
                                isValid = false;
                            }
                        }
                    }

                }
            }

        return isValid;
    }
}
